#include <stdio.h>
#include <stdlib.h>
#include <GeeJoan.h>
#include <string.h>
#define RESET   "\033[0m"
#define RED     "\033[31m"      /* Red */
#define GREEN   "\033[32m"      /* Green */
#define YELLOW  "\033[33m"      /* Yellow */
#define BLUE    "\033[34m"      /* Blue */

void printBuff(char *data, int len)
{
    printf("%s" , YELLOW);
    for (int i = 0; i < len; ++i)
    {
        printf( "%02X", data[i]&0xff);
    }
    printf("\0");


    printf("%s" , RESET);
}


int main()
{
    // 协议使用者案例
    // 网络包
    // 通过serialzeXXXXX 方法 可以序列化 对应的数据包
    // 同时数据包的可以使用者 deserialzeXXXXX 将 数据包的反序列化

    // 序列化的字节流 使用网络传输 , 接收方 即可反序列化出结果

    printf("%sTest NetWorkRequest%s\r\n" , YELLOW , RESET);

    // // NOTE 需要序列化 数据
    // Auth mod
    NetWorkPackageModel mod = NetWorkPackageModel_IOTMod;
    int sub_type = AUTH_LOGIN;
    long long taskid = 1;
    const char body[] = "test body";
    const char publicKey[] = "testkey";

    // 序列化 的字节流
    void *buffer = 0;

    // 引用传递 buff  和补充参数
    int len = serialzeNetWorkPackageRequest( &buffer, mod, sub_type,
                                             taskid, body, sizeof( body ), publicKey, sizeof( publicKey ));

    // 打印
    printf( "serial buffer: " );
    printBuff((char *) buffer, len );
    printf( "\n" );
    // 反序列化
    NetWorkPackageRequest *request;
    ERRORCODE ret = deserialzeNetWorkPackageRequest( &request, buffer, len );
    // 成功 , 判断是否
    if (ret == EXIT_SUCCESS)
    {
        printf( "deserialze registerApi : %sPASS%s\n", GREEN, RESET );
    } else
    {

        printf( "deserialze registerApi : %sNO PASS%s\n", RED, RESET );
    }
    // 判断 解密 后的 数据 和 原数据 是否 相同
    if (mod == request->type_m)
    {
        printf( "          mod deserial : %sPASS%s\n", GREEN, RESET );
    } else
    {
        printf( "          mod deserial : %sNO PASS%s\n", RED, RESET );
    }
    if ( sub_type == request->type_sub)
    {
        printf( "     sub_type deserial : %sPASS%s\n", GREEN, RESET );
    } else
    {
        printf( "     sub_type deserial : %sNO PASS%s\n", RED, RESET );
    }

    if (taskid == request->taskid)
    {
        printf( "       taskid deserial : %sPASS%s\n", GREEN, RESET );
    } else
    {
        printf( "       taskid deserial : %sNO PASS%s\n", RED, RESET );
    }

    if (memcmp( body , request->body.data, request->body.len) == 0)
    {
        printf( "         body deserial : %sPASS%s\n", GREEN, RESET );
    } else
    {
        printf( "         body deserial : %sNO PASS%s\n", RED, RESET );
    }

    if (memcmp( publicKey , request->pubilckey.data,request->pubilckey.len) == 0)
    {
        printf( "    publicKey deserial : %sPASS%s\n", GREEN, RESET );
    } else
    {
        printf( "    publicKey deserial : %sNO PASS%s\n", RED, RESET );
    }

    free( buffer ); // 释放内存
    free_NetWorkPackageRequest( request ); // 释放内存


    // 实际使用
    printf("\r\n%s真实环境的例子(登录案例)...%s\r\n" , YELLOW , RESET);
    printf("客户端的发出的数据包 ... \r\n");
    // 业务包
    char *loginBuffer = 0; //储存序列化后的数据包 buff
    const char* your_name = "testname";
    const char* your_password = "testpassword";
    int64_t currentTime = 1234567890123;
    //  & 才能修改为指针的buff
    int loginLen = serialzeLoginRequest(&loginBuffer , your_name ,  your_password , currentTime);

    if (loginLen < 0 )
    {
        fprintf(stderr , "serial Login Request Error \r\n");
        return -1;
    } else
    {
        printf("serial Login Request Success \r\n");
    }

    // 网络请求包
    char* networkPackageBuffer = 0 ;
    long long taskid_ = 2 ; // 当前的任务 实际环境 自增
    int networkPackageLen = serialzeNetWorkPackageRequest(&networkPackageBuffer , ///< 输出的网络包
            NetWorkPackageModel_AuthMod , ///< 鉴权模块
            AUTH_LOGIN , ///< 登录子模块
            taskid_ , ///< 本地的 任务
            loginBuffer , ///< 登录的 业务包
            loginLen , ///<  登录的业务包长度
            NULL ,///< 公钥 , NULL 空
            0  ///< 长度约0
            );

    printf("Request : ");
    printBuff(networkPackageBuffer , networkPackageLen );

    printf("\r\n");

    // 释放内存中
    if(loginBuffer)
    {
        free(loginBuffer);
    }
    if(networkPackageBuffer)
    {
        free(networkPackageBuffer);
    }

    // 输出
    // output: 080110021802221F0A08746573746E616D65120C7465737470617373776F726418CB89EC8FF723

    // 解包
    printf("\r\n解包 : \r\n");
    // 测试 的网络包
    const char *networkPackString = "080110021802221F0A08746573746E616D65120C7465737470617373776F726418CB89EC8FF723";
    // 获取源包 即 networkPackageBuffer
    void *decodePackage = 0;
    int decodeLen = HexString2Char(&decodePackage , networkPackString , strlen(networkPackString));
    if(decodeLen < 0 )
    {
        fprintf(stderr , "decode NetworkPackage Error \r\n");
        return -1;
    }

    // 网络包
    NetWorkPackageRequest *requestRecv = 0 ;
    ERRORCODE retCode = deserialzeNetWorkPackageRequest( &requestRecv , (void*)decodePackage  , decodeLen);
    // 释放了反序列化 的 包
    if (decodePackage){
        free(decodePackage);
    }
    if (retCode == ERROR_FAIL)
    {
        fprintf(stderr , "deserialzeNetWorkPackageRequest Error \r\n");
        return -1;
    } else
    {
        printf( "deserialzeNetWorkPackageRequest Success \r\n");
    }

    printf( "Model : %d \r\n" , requestRecv->type_m);
    printf( "Type  : %d \r\n" , requestRecv->type_sub);
    printf( "Taskid: %lld \r\n" , requestRecv->taskid);

    printf("根据类型 解出业务包\r\n");
    if (requestRecv->type_sub == AUTH_LOGIN)
    {
        LoginRequest *loginRequest = 0 ;

        if(deserialzeLoginRequest(&loginRequest , requestRecv->body.data , requestRecv->body.len) == ERROR_FAIL)
        {
            fprintf(stderr , "deserialzeLoginRequest Error \r\n");
            return -1;
        }
        //
        printf("Name  : %s \r\n", loginRequest->username);
        printf("Passwd: %s \r\n", loginRequest->password);
        printf("time  : %lld \r\n", loginRequest->timestamp);

        // 释放了业务包
        free_LoginRequest(loginRequest);
    }

    // 释放网络包
    free_NetWorkPackageRequest(requestRecv);


    return 0;
}